# -*- coding: utf-8 -*-

import platform
import struct
import glob
import shutil
import os
import fnmatch
import subprocess
import sys
import re
import stat
import json
from . import common



def log(text = ""):
  """
  打印调试内容
  """
  if common.LOG:
    print(text)



def host_platform():
  """
  查看操作系统类型，返回内容： mac/linux/win32/win64
  """
  ret = platform.system().lower()
  if (ret == "darwin"):
    return "mac"
  return ret


def os_name():
  """
  查看操作系统  ubuntu/cenos/win32/win64/macos
  """
  name = "";
  if is_file("/etc/os-release"):
    with open("/etc/os-release", "r") as lines:
      for line in lines:
        if line.startswith("ID="):
          name = line.split("=")[1];
          if name.startswith("\"") and name.endswith("\""):
            name : str = name.mid(1, name.__len__() - 2)
          name = name.replace("\n", "");
          name = name.replace("\r", "");
          name = name.replace(" ", "");
          name = name.lower();
  return name;



def docker_version():
  """
  查看docker版本
  """
  content = ""
  content = cmd_with_content("docker", ["-v"])
  start = content.index("Docker version ") + 15
  end = content.index(", build ")
  version = content[start: end]
  versions = version.split(".")
  return int(versions[0]);
  

def is_os_64bit():
  """
  返回操作系统是否为 x64
  """
  return platform.machine().endswith('64')



def is_os_arm():
  """
  返回操作系统是否基于 arm
  """
  if -1 == platform.machine().find('arm'):
    return False
  return True



def is_kylin():
  """
  是否为龙芯操作系统
  """
  return 'kylin' == os_name()


def is_python_64bit():
  """
  返回安装的python是否为x64版本
  """
  return (struct.calcsize("P") == 8)



def get_path(path):
  """
  归一化路径，如果是windows平台，将/转化为\\
  """
  if "windows" == host_platform():
    return path.replace("/", "\\")
  return path



def get_env(name):
  """
  获取环境变量
  """
  return os.getenv(name, "")



def set_env(name, value):
  """
  设置环境变量
  """
  os.environ[name] = value
  return



def print_info(info=""):
  """
  打印信息
  """
  print("------------------------------------------")
  print(info)
  print("------------------------------------------")
  return


def print_error(error=""):
  """
  打印错误信息
  """
  print("\033[91m" + error + "\033[0m")



def print_list(list):
  """
  以 [] 的格式，打印列表
  """
  print('[%s]' % ', '.join(map(str, list)))
  return



def is_file(path):
  """
  判断文件是否存在，或指定路径是否为文件
  """
  return os.path.isfile(get_path(path))


def is_dir(path):
  """
  判断文件夹是否存在，或指定路径是否为文件夹
  """
  return os.path.isdir(get_path(path))


def is_exist(path):
  """
  是否存在文件或文件夹
  """
  if is_file(path) or is_dir(path):
    return True
  return False



def is_root():
  """
  判断当前是否为root账号
  """
  if is_windows():
    return False
  return os.geteuid() == 0;



def copy_file(src, dst):
  """
  复制文件到指定目录
  """
  if is_file(dst):
    delete_file(dst)
  if not is_file(src):
    print("copy warning [file not exist]: " + src)
    return
  return shutil.copy2(get_path(src), get_path(dst))



def move_file(src, dst):
  """
  移动文件到指定目录
  """
  if is_file(dst):
    delete_file(dst)
  if not is_file(src):
    print("move warning [file not exist]: " + src)
    return
  return shutil.move(get_path(src), get_path(dst))



def copy_files(src, dst, override=True):
  """
  复制文件夹到指定文件夹（覆盖）
  """
  for file in glob.glob(src):
    file_name = os.path.basename(file)
    if is_file(file):
      if override and is_file(dst + "/" + file_name):
        delete_file(dst + "/" + file_name)
      if not is_file(dst + "/" + file_name):
        copy_file(file, dst)
    elif is_dir(file):
      if not is_dir(dst + "/" + file_name):
        create_dir(dst + "/" + file_name)
      copy_files(file + "/*", dst + "/" + file_name, override)
  return



def move_files(src, dst, override=True):
  """
  移动文件夹到指定文件夹（覆盖）
  """
  for file in glob.glob(src):
    file_name = os.path.basename(file)
    if is_file(file):
      if override and is_file(dst + "/" + file_name):
        delete_file(dst + "/" + file_name)
      if not is_file(dst + "/" + file_name):
        move_file(file, dst)
    elif is_dir(file):
      if not is_dir(dst + "/" + file_name):
        create_dir(dst + "/" + file_name)
      move_files(file + "/*", dst + "/" + file_name, override)
  return



def delete_file(path):
  """
  删除文件
  """
  if not is_file(path):
    print("delete warning [file not exist]: " + path)
    return
  return os.remove(get_path(path))


def create_dir(path):
  """
  创建文件夹
  """
  path2 = get_path(path)
  if not os.path.exists(path2):
    os.makedirs(path2)
  return


def delete_dir(path):
  """
  删除文件夹
  """
  if not is_dir(path):
    print("delete warning [folder not exist]: " + path)
    return
  shutil.rmtree(get_path(path), ignore_errors=True)
  return


def readFile(path):
  """
  读取文件内容
  """
  if not is_file(path):
    return ""
  filedata = ""
  with open(get_path(path), "r") as file:
    filedata = file.read()
  return filedata



def writeFile(path, data, append=False):
  """
  写入文件内容
  """
  if not append:
    if is_file(path):
      delete_file(path)
  with open(get_path(path), "w") as file:
    file.write(data)
  return



def cmd(prog, args=[], is_no_errors=False): 
  """
  运行命令行，并返回操作结果（0表示成功，其他表示错误）
  """
  if common.LOG:
    print("执行命令:" + prog + " " + " ".join(args))
  ret = 0
  if ("windows" == host_platform()):
    sub_args = args[:]
    sub_args.insert(0, get_path(prog))
    ret = subprocess.call(sub_args, stderr=subprocess.STDOUT, shell=True)


  else:
    command = prog
    for arg in args:
      command += (" \"" + arg + "\"")
    if not is_root():
      command = "sudo " + command
    ret = subprocess.call(command, stderr=subprocess.STDOUT, shell=True)
  if ret != 0 and not is_no_errors:
    sys.exit("Error (" + prog + "): " + str(ret))
  return ret


def cmd_with_content(prog, args=[]):  
  """
  运行命令行，并返回 命令行内容
  """
  if common.LOG:
    print("执行命令:" + prog + " " + " ".join(args))
  ret = ""
  if ("windows" == host_platform()):
    sub_args = args[:]
    sub_args.insert(0, get_path(prog))
    ret = subprocess.getoutput(sub_args, stderr=subprocess.STDOUT, shell=True)
  else:
    command = prog
    for arg in args:
      command += (" \"" + arg + "\"")
    if not is_root():
      command = "sudo " + command
    ret = subprocess.getoutput(command)
  return ret


def cmd_in_dir(directory, prog, args=[], is_no_errors=False):
  """
  在指定目录里运行命令
  """
  if common.LOG:
    print(f"在目录 {directory} 执行命令:" + prog + " " + " ".join(args))
  dir = get_path(directory)
  cur_dir = os.getcwd()
  os.chdir(dir)
  next_dir = os.getcwd()
  if prog.endswith(".sh"):
    cmd("chmod", ["777", prog])
  ret = cmd(prog, args, is_no_errors)
  os.chdir(cur_dir)
  return ret



def get_cwd():
  """
  返回当前工作目录
  """
  return os.getcwd()


def ping(host : str):
  '''
  ping一个域名
  '''
  # Option for the number of packets as a function of
  param = '-n' if platform.system().lower()=='windows' else '-c'
  # Building the command. Ex: "ping -c 1 google.com"
  command = ['ping', param, '1', host]
  return subprocess.call(command) == 0


def set_cwd(dir):
  """
  设置当前工作目录
  """
  os.chdir(dir)
  return

def is_windows():
  """
  是否是windows操作系统
  """
  if "windows" == host_platform():
    return True
  return False


def platform_is_32(platform):
  """
  是否为32位操作系统
  """
  if (-1 != platform.find("_32")):
    return True
  return False



def host_platform_is64():
  """
  是否为64位操作系统
  """
  return platform.machine().endswith("64")



def download(url, dst):
  """
  下载文件
  """
  if(is_windows()):
    return cmd(".\\tools\\curl.exe", ["-L", "-o", dst, url])
  else:
    return cmd("curl", ["-L", "-o", dst, url])


def extract(src, dst):
  """
  解压文件
  """
  if(is_windows()):
    app = ".\\tools\\7z.exe"
  else:
    app = "7za" if ("mac" == host_platform()) else "7z"
  return cmd(app, ["x", "-y", src, "-o" + dst])



def is_cmd_exist(command : str) -> bool :
  """
  检查命令行是否存在
  """
  ret = cmd(command, ["-v"], True)
  if ret == 0:
    return True;
  ret = cmd(command, ["--version"], True)
  return ret == 0;



def remove_docker_container(container_name):
  cmd("docker", ["container", "rm", container_name, "-f"])
  return True


def check_docker_container(container_name):
  """
  检查某个container 容器是否在运行(linux平台)
  """
  if not is_cmd_exist("docker"):
    return False;
  if docker_version() <= 20:
    ## 国产麒麟版本的docker版本较低，需要用另一种方式查询docker容器
    # json_str = cmd_with_content("docker", ["container", "ls", "--format", "\"{\\\"Names\\\": \\\"{{.Names}}\\\"}\"", "-a"])
    json_str = cmd_with_content("docker", ["container", "ls", "--format", "\"Names={{.Names}};State={{.State}}\"", "-a"])
    for j in json_str.split('\n'):
      if j.__contains__(f"Names={container_name};"):
        return True;
  else:
    json_str = cmd_with_content("docker", ["container", "ls", "--format", "json", "-a"])

    json_str = json_str.strip()
    if json_str == '':
      return False
    json_str = json_str.split('\n')
    for j in json_str:
      jj = json.loads(j)
      if jj["Names"] == container_name:
        return True;

  return False;
  


def check_service(service_name):
  """
  检查 是否存在某服务(windows平台)
  """
  ret = cmd("sc", ["query", service_name], True)
  return ret == 0;
  


def is_container_running(container_name):
  """
  检查某个容器是否正在运行(linux平台)
  """
  
  if not is_cmd_exist("docker"):
    return False;
  if docker_version() <= 20:
    ## 国产麒麟版本的docker版本较低，需要用另一种方式查询docker容器
    # json_str = cmd_with_content("docker", ["container", "ls", "--format", "\"{\\\"Names\\\": \\\"{{.Names}}\\\", \\\"State\\\": \\\"{{.State}}\\\"}\"", "-a"])
    json_str = cmd_with_content("docker", ["container", "ls", "--format", "\"Names={{.Names}};State={{.State}}\"", "-a"])
    
    for j in json_str.split('\n'):
      if j.__contains__(f"Names={container_name};") and j.__contains__(f"State=running"):
        return True;
  else:
    json_str = cmd_with_content("docker", ["container", "ls", "--format", "json", "-a"])
    json_str = json_str.strip()
    if json_str == '':
      return False
    json_str = json_str.split('\n')
    for j in json_str:
      jj = json.loads(j)
      if jj["Names"] == container_name and jj["State"] == 'running' :
        return True;

  return False;



def is_apt() -> bool:
  ''' 查看是否支持apt安装包
  
  Parameters
  ----------
  
  
  Returns
  -------
  bool
  
  '''
  
  return cmd("apt", ["-v"], True) == 0



def is_service_running(service_name):
  """
  检查 某服务是否正在运行
  """
  if not is_windows():
    content = cmd_with_content("systemctl", ["is-active", service_name]);
    if content == 'active':
        return True
    return False
  ret = cmd_with_content("sc", ["query", service_name])
  list = ret.split("\n")
  for line in list:

    l = line.strip()
    if l.startswith('STATE'):
      return l.__contains__('RUNNING')
  return False;
  